/*
 * @Author: Clark
 * @Email: haixuanwoTxh@gmail.com
 * @Date: 2023-01-04 10:37:09
 * @LastEditors: Clark
 * @LastEditTime: 2023-01-04 11:05:15
 * @Description: file content
 */

#include "apue.h"

#include <errno.h>
#include <stdarg.h>

static void err_doit(int, int, const char*, va_list);

/**
 * @brief 使用系统调用打印信息
 * @param fmt 格式化参数
 * @param ...
 */
void err_ret(const char* fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    err_doit(1, errno, fmt, ap);
    va_end(ap);
}

/**
 * @brief 使用系统调用打印信息，并终止进程
 * @param fmt 格式化参数
 * @param ...
 */
void err_sys(const char* fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    err_doit(1, errno, fmt, ap);
    va_end(ap);

    exit(1);
}

/**
 * @brief 使用系统调用打印信息
 * @param error 错误码
 * @param fmt 格式化参数
 * @param ...
 */
void err_cont(int error, const char* fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    err_doit(1, errno, fmt, ap);
    va_end(ap);

    exit(1);
}

/**
 * @brief 使用系统调用打印信息，并终止进程
 * @param error 错误码
 * @param fmt 格式化参数
 * @param ...
 */
void err_exit(int error, const char* fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    err_doit(1, errno, fmt, ap);
    va_end(ap);

    exit(1);
}

/**
 * @brief 使用系统调用打印信息，并dump core终止进程
 * @param fmt 格式化参数
 * @param ...
 */
void err_dump(const char* fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    err_doit(1, errno, fmt, ap);
    va_end(ap);

    abort();    // dump core and terminate
    //exit(1);
}

/**
 * @brief 使用系统调用打印信息
 * @param fmt 格式化参数
 * @param ...
 */
void err_msg(const char* fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    err_doit(0, 0, fmt, ap);
    va_end(ap);
}

/**
 * @brief 使用系统调用打印信息
 * @param fmt 格式化参数
 * @param ...
 */
void err_quit(const char* fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    err_doit(0, 0, fmt, ap);
    va_end(ap);
    exit(1);
}

/**
 * @brief 打印信息
 * @param errnoflag 错误标志
 * @param error
 * @param fmt
 * @param ap
 */
static void err_doit(int errnoflag, int error, const char *fmt, va_list ap)
{
    char buf[MAXLINE] = {0};

    vsnprintf(buf, MAXLINE - 1, fmt, ap);
    if (errnoflag)
    {
        snprintf(buf + strlen(buf), MAXLINE - strlen(buf) - 1, ": %s", strerror(error));
    }

    strcat(buf, "\n");
    fflush(stdout);
    fputs(buf, stderr);
    fflush(NULL);
}
